package ar.edu.caece.compiler.grammar.factories;

import ar.edu.caece.compiler.grammar.AbstractTokenVisitorFactory;
import ar.edu.caece.compiler.grammar.Recognizer;
import ar.edu.caece.compiler.grammar.TokenRecognizer;
import ar.edu.caece.compiler.grammar.TokenVisitor;
import ar.edu.caece.compiler.grammar.attributes.Attribute;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeDeclaraciones;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeFuncProc;
import ar.edu.caece.compiler.grammar.nonterminals.BLOQUE;
import ar.edu.caece.compiler.grammar.nonterminals.DECLARACION;
import ar.edu.caece.compiler.grammar.nonterminals.LISTADECLARACIONES;
import ar.edu.caece.compiler.grammar.nonterminals.LISTADECLARACIONES1;

public class LISTADECLARACIONES1Factory extends AbstractTokenVisitorFactory {

	private static LISTADECLARACIONES1Factory INSTANCE;
	
	public static LISTADECLARACIONES1Factory getInstance() throws Exception {
		if(INSTANCE==null) INSTANCE = new LISTADECLARACIONES1Factory();
		return INSTANCE;
	}
	
	private DECLARACIONFactory declaracionFactory;
	private LISTADECLARACIONESFactory listadeclaracionesFactory;
	private TokenVisitor parseDECLARACION;
	private TokenVisitor parseLISTADECLARACIONES;
	
	private Initializer initializer = new Initializer() {
		
		@Override
		public void init() throws Exception {
			initializer = NoOperationInitializer.getInstance();
			declaracionFactory = DECLARACIONFactory.getInstance();
			listadeclaracionesFactory = LISTADECLARACIONESFactory.getInstance();
			parseLISTADECLARACIONES = listadeclaracionesFactory.makeVisitor();
			parseDECLARACION = declaracionFactory.makeVisitor();
		}
	};
	
	private LISTADECLARACIONES1Factory() throws Exception {

	}
	
	@Override
	public TokenVisitor makeChainedVisitor(
			final TokenVisitor siguiente) throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador)
					throws Exception {
				TokenVisitor parseDECLARACION2 = declaracionFactory.makeChainedVisitor(siguiente);
				parseDECLARACION2.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parseDECLARACION2.addInheretedAttribute(Attribute.ARBOL_HEREDADO, getAttribute(Attribute.ARBOL_HEREDADO));
				Recognizer result = llamador.execute(parseDECLARACION2);
				if(result instanceof DECLARACION) {					
					DECLARACION declaracion = (DECLARACION) result;
					if(declaracion instanceof BLOQUE) {
						NodeFuncProc bloque = (NodeFuncProc) declaracion.getAttribute(Attribute.ARBOL_SINTETIZADO);
						
						NodeDeclaraciones declaraciones = (NodeDeclaraciones) getAttribute(Attribute.ARBOL_HEREDADO);
						declaraciones.addProcedimiento(bloque);
						declaracion.addAttribute(Attribute.ARBOL_SINTETIZADO, declaraciones);
					}
					
					parseLISTADECLARACIONES.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,declaracion.getAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA));
					parseLISTADECLARACIONES.addInheretedAttribute(Attribute.ARBOL_HEREDADO, declaracion.getAttribute(Attribute.ARBOL_SINTETIZADO));

					LISTADECLARACIONES listadeclaraciones = (LISTADECLARACIONES) nextToken().execute(parseLISTADECLARACIONES);
					LISTADECLARACIONES1 listadeclaraciones1 = new LISTADECLARACIONES1 (declaracion, listadeclaraciones);
					
					listadeclaraciones1.addAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA,listadeclaraciones.getAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA));
					
					listadeclaraciones1.addAttribute(Attribute.ARBOL_SINTETIZADO, listadeclaraciones.getAttribute(Attribute.ARBOL_SINTETIZADO));
					return listadeclaraciones1;
				} 
				else {
					return result;
				}
			}
			
		};
	
	}
	@Override
	public TokenVisitor makeVisitor() throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador) throws Exception {

				parseDECLARACION.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));		
				parseDECLARACION.addInheretedAttribute(Attribute.ARBOL_HEREDADO, getAttribute(Attribute.ARBOL_HEREDADO));
				
				DECLARACION declaracion = (DECLARACION) llamador.execute(parseDECLARACION);
				
				if(declaracion instanceof BLOQUE) {
					NodeFuncProc bloque = (NodeFuncProc) declaracion.getAttribute(Attribute.ARBOL_SINTETIZADO);
					
					NodeDeclaraciones declaraciones = (NodeDeclaraciones) getAttribute(Attribute.ARBOL_HEREDADO);
					declaraciones.addProcedimiento(bloque);
					declaracion.addAttribute(Attribute.ARBOL_SINTETIZADO, declaraciones);
				}
				parseLISTADECLARACIONES.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,declaracion.getAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA));
				parseLISTADECLARACIONES.addInheretedAttribute(Attribute.ARBOL_HEREDADO, declaracion.getAttribute(Attribute.ARBOL_SINTETIZADO));
				
				LISTADECLARACIONES listadeclaraciones = (LISTADECLARACIONES) nextToken().execute(parseLISTADECLARACIONES);
				LISTADECLARACIONES1 listadeclaraciones1 = new LISTADECLARACIONES1 (declaracion, listadeclaraciones);
				
				listadeclaraciones1.addAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA,listadeclaraciones.getAttribute(Attribute.TABLA_SIMBOLOS_SINTETIZADA));
				listadeclaraciones1.addAttribute(Attribute.ARBOL_SINTETIZADO, listadeclaraciones.getAttribute(Attribute.ARBOL_SINTETIZADO));
				return listadeclaraciones1;
			}
		};
	}
	
	
}
